import { Tile_Struct } from "./tile_struct";
import { BitMath } from "../math/math";
import { Tile_Bank } from "./tile_bank";
import { Tile_Element } from "./tile_tile";

export namespace Tile_Tool
{
    export class TileTool
    {
        public static ComputeTileDataHash(data: Tile_Struct.TileData): string
        {
            let hex = "";

            var bts = data.ToBytes();
            for (var i = 0; i < bts.length; i++)
            {
                var hexstr = i.toString(16);
                if (hexstr.length == 1)
                    hex += "0" + hexstr;
                else
                    hex += hexstr;
            }

            return hex;
        }
        static FromRgb(color: BitMath.Color32, r: number, g: number, b: number): void
        {
            color.r = r;
            color.g = g;
            color.b = b;
        }
        public static GetNesPalette(): BitMath.OutPalette
        {

            let colors: BitMath.Color32[] = [];
            for (var i = 0; i < 256; i++)
                colors.push(new BitMath.Color32());

            TileTool.FromRgb(colors[0x0], 84, 84, 84);
            TileTool.FromRgb(colors[0x1], 0, 30, 116);
            TileTool.FromRgb(colors[0x2], 8, 16, 144);
            TileTool.FromRgb(colors[0x3], 48, 0, 136);
            TileTool.FromRgb(colors[0x4], 68, 0, 100);
            TileTool.FromRgb(colors[0x5], 92, 0, 48);
            TileTool.FromRgb(colors[0x6], 84, 4, 0);
            TileTool.FromRgb(colors[0x7], 60, 24, 0);
            TileTool.FromRgb(colors[0x8], 32, 42, 0);
            TileTool.FromRgb(colors[0x9], 8, 58, 0);
            TileTool.FromRgb(colors[0xa], 0, 64, 0);
            TileTool.FromRgb(colors[0xb], 0, 60, 0);
            TileTool.FromRgb(colors[0xc], 0, 50, 60);
            TileTool.FromRgb(colors[0xd], 0, 0, 0);
            TileTool.FromRgb(colors[0xe], 0, 0, 0);
            TileTool.FromRgb(colors[0xf], 0, 0, 0);
            TileTool.FromRgb(colors[0x10], 152, 150, 152);
            TileTool.FromRgb(colors[0x11], 8, 76, 196);
            TileTool.FromRgb(colors[0x12], 48, 50, 236);
            TileTool.FromRgb(colors[0x13], 92, 30, 228);
            TileTool.FromRgb(colors[0x14], 136, 20, 176);
            TileTool.FromRgb(colors[0x15], 160, 20, 100);
            TileTool.FromRgb(colors[0x16], 152, 34, 32);
            TileTool.FromRgb(colors[0x17], 120, 60, 0);
            TileTool.FromRgb(colors[0x18], 84, 90, 0);
            TileTool.FromRgb(colors[0x19], 40, 114, 0);
            TileTool.FromRgb(colors[0x1a], 8, 124, 0);
            TileTool.FromRgb(colors[0x1b], 0, 118, 40);
            TileTool.FromRgb(colors[0x1c], 0, 102, 120);
            TileTool.FromRgb(colors[0x1d], 0, 0, 0);
            TileTool.FromRgb(colors[0x1e], 0, 0, 0);
            TileTool.FromRgb(colors[0x1f], 0, 0, 0);
            TileTool.FromRgb(colors[0x20], 236, 238, 236);
            TileTool.FromRgb(colors[0x21], 76, 154, 236);
            TileTool.FromRgb(colors[0x22], 120, 124, 236);
            TileTool.FromRgb(colors[0x23], 176, 98, 236);
            TileTool.FromRgb(colors[0x24], 228, 84, 236);
            TileTool.FromRgb(colors[0x25], 236, 88, 180);
            TileTool.FromRgb(colors[0x26], 236, 106, 100);
            TileTool.FromRgb(colors[0x27], 212, 136, 32);
            TileTool.FromRgb(colors[0x28], 160, 170, 0);
            TileTool.FromRgb(colors[0x29], 116, 196, 0);
            TileTool.FromRgb(colors[0x2a], 76, 208, 32);
            TileTool.FromRgb(colors[0x2b], 56, 204, 108);
            TileTool.FromRgb(colors[0x2c], 56, 180, 204);
            TileTool.FromRgb(colors[0x2d], 60, 60, 60);
            TileTool.FromRgb(colors[0x2e], 0, 0, 0);
            TileTool.FromRgb(colors[0x2f], 0, 0, 0);
            TileTool.FromRgb(colors[0x30], 236, 238, 236);
            TileTool.FromRgb(colors[0x31], 168, 204, 236);
            TileTool.FromRgb(colors[0x32], 188, 188, 236);
            TileTool.FromRgb(colors[0x33], 212, 178, 236);
            TileTool.FromRgb(colors[0x34], 236, 174, 236);
            TileTool.FromRgb(colors[0x35], 236, 174, 212);
            TileTool.FromRgb(colors[0x36], 236, 180, 176);
            TileTool.FromRgb(colors[0x37], 228, 196, 144);
            TileTool.FromRgb(colors[0x38], 204, 210, 120);
            TileTool.FromRgb(colors[0x39], 180, 222, 120);
            TileTool.FromRgb(colors[0x3a], 168, 226, 144);
            TileTool.FromRgb(colors[0x3b], 152, 226, 180);
            TileTool.FromRgb(colors[0x3c], 160, 214, 228);
            TileTool.FromRgb(colors[0x3d], 160, 162, 160);
            TileTool.FromRgb(colors[0x3e], 0, 0, 0);
            TileTool.FromRgb(colors[0x3f], 0, 0, 0);

            //transparent
            colors[0x0d].a = 0;
            let op = BitMath.OutPalette.Init(colors, 0x0D);
            for (var i = 0; i < 0x3f; i++)
                op.openTag[i] = 1;
            return op;
        }

        public static GenBlock(): Tile_Struct.TileData
        {
            var cdata = Tile_Struct.TileData.Create(Tile_Struct.ColorBitLen.Bit1, 8, 8);
            if (cdata.palette != null && cdata.palette.palette != null)
            {
                cdata.palette.palette[0] = 0x0d;
                cdata.palette.palette[1] = 0x30;
                if (cdata.tiledata != null)
                {
                    for (var i = 0; i < cdata.tiledata.length; i++)
                    {
                        cdata.tiledata[i] = 0xff;
                    }
                }

            }
            return cdata;
        }
        public static GenGridTileData(): Tile_Struct.TileData
        {
            //基本初始化
            let data = Tile_Struct.TileData.Create(Tile_Struct.ColorBitLen.Bit2, 8, 8);
            if (data.palette != null && data.palette.palette != null && data.tiledata != null)
            {
                data.palette.palette[0] = 0x0D;
                data.palette.palette[1] = 0x18;
                data.palette.palette[2] = 0x24;
                data.palette.palette[3] = 0x09;
                for (var y = 0; y < 8; y++)
                {
                    for (var x = 0; x < 8; x += 4) //一个字节存四个像素
                    {
                        var jump = ((((y / 4) % 2) + (x / 4) % 2) % 2 == 1);
                        var color = jump ? 1 : 2;

                        var color1 = jump ? 1 : 2;
                        var color2 = color;
                        var color3 = color1;
                        var outbyte = (color << 6) | (color1 << 4) | (color2 << 2) | (color3 << 0);

                        data.tiledata[y * 2 + x / 4] = outbyte;
                    }
                }
            }
            return data;
        }
        public static GenOneColorTileData(colorIndex: number, colorTran: number = 0x0D): Tile_Struct.TileData
        {
            let data = Tile_Struct.TileData.Create(Tile_Struct.ColorBitLen.Bit1, 8, 8);
            if (data.palette != null && data.palette.palette != null)
            {
                data.palette.palette[0] = colorTran;
                data.palette.palette[1] = colorIndex;
                var linedata = new Uint8Array([1, 1, 1, 1, 1, 1, 1, 1]);
                for (var y = 0; y < 8; y++)
                    data.SetLine(y, linedata);
            }
            return data;
        }
        public static GenOnePixelBorder(left: boolean, top: boolean, right: boolean, bottom: boolean, colorIndex: number = 0x30, colorTran: number = 0x0D): Tile_Struct.TileData
        {
            let data = Tile_Struct.TileData.Create(Tile_Struct.ColorBitLen.Bit1, 8, 8);
            if (data.palette != null && data.palette.palette != null)
            {
                data.palette.palette[0] = colorTran;
                data.palette.palette[1] = colorIndex;
                data.SetLineBool(0, [left || top, top, top, top, top, top, top, top || right]);
                data.SetLineBool(1, [left, false, false, false, false, false, false, right]);
                data.SetLineBool(2, [left, false, false, false, false, false, false, right]);
                data.SetLineBool(3, [left, false, false, false, false, false, false, right]);
                data.SetLineBool(4, [left, false, false, false, false, false, false, right]);
                data.SetLineBool(5, [left, false, false, false, false, false, false, right]);
                data.SetLineBool(6, [left, false, false, false, false, false, false, right]);
                data.SetLineBool(7, [left || bottom, bottom, bottom, bottom, bottom, bottom, bottom, right || bottom]);
            }
            return data;
        }
        public static GenTwoPixelBorder(left: boolean, top: boolean, right: boolean, bottom: boolean, colorIndex: number = 0x30, colorTran: number = 0x0D): Tile_Struct.TileData
        {
            let data = Tile_Struct.TileData.Create(Tile_Struct.ColorBitLen.Bit1, 8, 8);
            if (data.palette != null && data.palette.palette != null)
            {
                data.palette.palette[0] = colorTran;
                data.palette.palette[1] = colorIndex;
                let lt = left || top;
                let rt = right || top;
                let lb = left || bottom;
                let rb = right || bottom;
                let l_ = left;
                let r_ = right;
                let _t = top;
                let _b = bottom;
                let __ = false;
                let txl = top && !left;
                let lxt = left && !top;
                let txr = top && !right;
                let rxt = right && !top;
                let bxl = bottom && !left;
                let lxb = left && !bottom;
                let bxr = bottom && !right;
                let rxb = right && !bottom;
                data.SetLineBool(0, [lt, _t, lt, _t, _t, rt, _t, rt]);
                data.SetLineBool(1, [l_, __, lxt, __, __, rxt, __, r_]);
                data.SetLineBool(2, [lt, txl, lt, _t, _t, rt, txr, rt]);
                data.SetLineBool(3, [l_, __, l_, __, __, r_, __, r_]);
                data.SetLineBool(4, [l_, __, l_, __, __, r_, __, r_]);
                data.SetLineBool(5, [lb, bxl, lb, _b, _b, rb, bxr, rb]);
                data.SetLineBool(6, [l_, __, lxb, __, __, rxb, __, r_]);
                data.SetLineBool(7, [lb, _b, lb, _b, _b, rb, _b, rb]);
            }
            return data;
        }
        public static LoadBlock(bank: Tile_Bank.Bank): Tile_Element.RenderTile
        {
            var old = bank.GetTileByName("block");
            if (old != null)
                return old;
            return bank.CreateTile("block", TileTool.GenBlock());
        }
        public static LoadASCII12toBank(data: Uint8Array, bank: Tile_Bank.Bank): void
        {
            //byte[] data = System.IO.File.ReadAllBytes("resources/ASC12");

            for (var i = 32; i < 127; i++)
            {
                var cdata = Tile_Struct.TileData.Create(Tile_Struct.ColorBitLen.Bit1, 6, 12);
                if (cdata.palette != null && cdata.palette.palette != null)
                {
                    cdata.palette.palette[0] = 0x0d;
                    cdata.palette.palette[1] = 0x30;
                    if (cdata.tiledata != null)
                    {
                        for (var j = 0; j < 12 - 1; j++)//向下移动一个像素 ，ASCII 12 英文字体比较小，移动一下，整齐一些
                        {
                            cdata.tiledata[j + 1] = data[(i - 32) * 12 + j];
                        }
                    }
                    //bank.CreateTile(((char)i).ToString(), cdata);
                    let s = String.fromCharCode(i);

                    bank.RegTileData(s, cdata);
                }
            }

            //放入12点阵光标 
            if (bank.GetTileByName("cursor") == null)
            {
                var cdata = Tile_Struct.TileData.Create(Tile_Struct.ColorBitLen.Bit1, 6, 12);
                if (cdata.palette != null && cdata.palette.palette != null)
                {
                    cdata.palette.palette[0] = 0x0d;
                    cdata.palette.palette[1] = 0x30;
                    if (cdata.tiledata != null)
                    {
                        for (var i = 0; i < 12; i++)
                        {
                            var line = new Uint8Array([1, 0, 0, 0, 0, 0, 0, 0])//setLine函数，要求字节对齐
                            cdata.SetLine(i, line);
                        }
                    }
                    //光标特别命名很独特
                    bank.RegTileData("cursor", cdata);
                }
            }

        }
        public static LoadHZK12toBank(data: Uint8Array, mapdata: Uint8Array, bank: Tile_Bank.Bank): void
        {
            //byte[] mapdata = System.IO.File.ReadAllBytes("resources/UTF16CONV");
            let mapGB2Utf16: { [id: number]: string } = {}
            for (var i = 0; i < mapdata.length / 4; i++)
            {
                var key = (mapdata[i * 4 + 0] + mapdata[i * 4 + 1] * 256);
                var value = String.fromCharCode(mapdata[i * 4 + 2] + mapdata[i * 4 + 3] * 256);
                mapGB2Utf16[key] = value;
            }
            //FOR GB2312
            //Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            //byte[] data = System.IO.File.ReadAllBytes("resources/HZK12");

            //List<byte> mapGB2Utf16 = new List<byte>();
            let charcount = 0;
            var areacount = data.length / 24 / 94;

            //List < byte > savemap = new List<byte>();

            for (var iQu = 0; iQu < 94; iQu++)
            {
                for (var iWei = 0; iWei < 94; iWei++)
                {
                    var cdata = Tile_Struct.TileData.Create(Tile_Struct.ColorBitLen.Bit1, 12, 12);
                    if (cdata.palette != null && cdata.palette.palette != null)
                    {
                        cdata.palette.palette[0] = 0x0d;
                        cdata.palette.palette[1] = 0x30;
                    }
                    var istart = (iQu * 94 + iWei) * 24;//从这里开始，24个字节
                    if (istart + 24 > data.length) break;
                    let allzero = true;
                    if (cdata.tiledata != null)
                    {
                        for (var k = 0; k < 24; k++)
                        {
                            cdata.tiledata[k] = data[istart + k];
                            if (cdata.tiledata[k] != 0)
                                allzero = false;
                        }
                    }
                    if (allzero)
                    {
                        continue;
                    }

                    var key = (0xa1 + iWei) * 256 + (0xa1 + iQu);
                    var hz = mapGB2Utf16[key];
                    //save map file
                    //因为GB2312编码器默认不可用，所以用个mapfile 干掉他
                    //var hz2 = System.Text.Encoding.GetEncoding("GB2312").GetString(gbcode);
                    //if (hz2.Length > 1)
                    //    continue;
                    //var hzdata = System.Text.Encoding.Unicode.GetBytes(hz2);
                    //savemap.Add(gbcode[0]);
                    //savemap.Add(gbcode[1]);
                    //savemap.Add(hzdata[0]);
                    //savemap.Add(hzdata[1]);

                    bank.RegTileData(hz, cdata);
                    //bank.CreateTile(hz, cdata);
                    charcount++;

                }
            }


            //放入12点阵光标 
            //放入12点阵光标 
            if (bank.GetTileByName("cursor") == null)
            {
                var cdata = Tile_Struct.TileData.Create(Tile_Struct.ColorBitLen.Bit1, 6, 12);
                if (cdata.palette != null && cdata.palette.palette != null)
                {
                    cdata.palette.palette[0] = 0x0d;
                    cdata.palette.palette[1] = 0x30;
                    if (cdata.tiledata != null)
                    {
                        for (var i = 0; i < 12; i++)
                        {
                            var line = new Uint8Array([1, 0, 0, 0, 0, 0, 0, 0])//setLine函数，要求字节对齐
                            cdata.SetLine(i, line);
                        }
                    }
                    //光标特别命名很独特
                    bank.RegTileData("cursor", cdata);
                }
            }
            //save map file
            //System.IO.File.WriteAllBytes("d:\\UTF16CONV", savemap.ToArray());

            console.log("Load HZK12:" + charcount);
        }
    }

}